package com.ygqh.baby.handler;

import com.ygqh.baby.model.FortuneBagDetail;
import com.ygqh.baby.model.FortuneBagDetailResult;
import com.ygqh.baby.po.YgFortuneBag;
import com.ygqh.baby.po.YgOrder;
import com.ygqh.baby.po.YgOrderDetail;
import com.ygqh.baby.po.YgStock;
import com.ygqh.baby.service.YgFortuneBagService;
import com.ygqh.baby.service.YgStockService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 福袋
 *
 * @author guohao
 */
@Component
public class FortuneBagHandler {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private YgFortuneBagService ygFortuneBagService;
    @Autowired
    private YgStockService ygStockService;

    public void reassemblyOrderDetails(YgOrder order) {
        logger.info("FortuneBagService.reassemblyOrderDetails param: {}", order);
        try {
            Map<String, List<YgOrderDetail>> odMap = order.getOrderDetail().stream().collect(Collectors.groupingBy(YgOrderDetail::getSkuCode));
            List<String> skuCodeList = new ArrayList<>(odMap.keySet());
            List<YgFortuneBag> fortuneBagList = ygFortuneBagService.findFortuneBagListWithStock("", skuCodeList, null);
            if (CollectionUtils.isEmpty(fortuneBagList)) {
                return;
            }
            List<FortuneBagDetail> bagDetailList = getFortuneBagDetailList(odMap, fortuneBagList);
            List<YgOrderDetail> orderDetailList = doReassemblyOrderDetails(order.getOrderDetail(), bagDetailList);
            order.setOrderDetail(orderDetailList);
            //扣库存
            deduceStock(bagDetailList);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("FortuneBagService.reassemblyOrderDetails: fail, orderId:{}, msg: {}", order.getOrderId(), e.getMessage());
            throw e;
        }
        logger.info("FortuneBagService.reassemblyOrderDetails response: {}", order);

    }

    private void deduceStock(List<FortuneBagDetail> bagDetailList) {


        List<YgStock> stockList = new ArrayList<>();
        for (FortuneBagDetail bagDetail : bagDetailList) {
            YgStock stock = new YgStock();
            stock.setSkuCode(bagDetail.getSrcSkuCode());
            stock.setAmount(Long.parseLong(bagDetail.getCount() + ""));
            stockList.add(stock);
        }
        ygStockService.reduceStock(stockList, "FortuneBag");
    }

    private List<YgOrderDetail> doReassemblyOrderDetails(List<YgOrderDetail> orderDetailList, List<FortuneBagDetail> bagDetailList) {
        Map<String, List<FortuneBagDetail>> listMap = bagDetailList.stream().collect(Collectors.groupingBy(FortuneBagDetail::getSkuCode));
        List<YgOrderDetail> newList = new ArrayList<>();

        int a = orderDetailList.size();
        for (YgOrderDetail orderDetail : orderDetailList) {
            List<FortuneBagDetail> bagDetails = listMap.get(orderDetail.getSkuCode());
            if (CollectionUtils.isNotEmpty(bagDetails)) {
                for (int i = 0; i < bagDetails.size(); i++) {
                    FortuneBagDetail bagDetail = bagDetails.get(i);
                    YgOrderDetail clone = orderDetail.clone();
                    if (i != 0) {
                        // 福袋商品明细，第一条明细保留原明细id；其它明细在原明细id上加原明细总长度，以防止与其它原明细id冲突
                        clone.setId(clone.getId() + a);
                        clone.setPromotionRemark("FortuneBagDetail");
                    }
                    clone.setSkuCode(bagDetail.getSrcSkuCode());
                    clone.setQuantity(Long.parseLong(bagDetail.getCount() + ""));
                    newList.add(clone);
                    a++;
                }
            } else {
                newList.add(orderDetail);
            }
        }

        return newList;
    }

    /**
     * 获取福袋明细
     *
     * @param odMap          订单明细
     * @param fortuneBagList 福袋集合
     * @return List<FortuneBagDetail>
     */
    private List<FortuneBagDetail> getFortuneBagDetailList(Map<String, List<YgOrderDetail>> odMap, List<YgFortuneBag> fortuneBagList) {
        List<FortuneBagDetail> bagDetailList = new ArrayList<>();
        //按福袋分组
        Map<String, List<YgFortuneBag>> bagMap = fortuneBagList.stream().collect(Collectors.groupingBy(YgFortuneBag::getSkuCode));
        for (Map.Entry<String, List<YgFortuneBag>> entry : bagMap.entrySet()) {
            //判断订单中是否存在该福袋商品，不存在跳过
            List<YgOrderDetail> orderDetailList = odMap.get(entry.getKey());
            if (CollectionUtils.isEmpty(orderDetailList)) {
                continue;
            }
            int quantity = orderDetailList.get(0).getQuantity().intValue();
            List<YgFortuneBag> bagList = entry.getValue();
            List<FortuneBagDetail> list = doEachBag(bagList, quantity);
            bagDetailList.addAll(list);
        }

        return mergeFortuneBagDetail(bagDetailList);
    }

    private List<FortuneBagDetail> mergeFortuneBagDetail(List<FortuneBagDetail> detailList) {
        if (detailList.size() == 1) {
            return detailList;
        }
        List<FortuneBagDetail> result = new ArrayList<>();
        Map<String, List<FortuneBagDetail>> collect = detailList.stream().collect(Collectors.groupingBy(FortuneBagDetail::getSrcSkuCode));
        for (Map.Entry<String, List<FortuneBagDetail>> entry : collect.entrySet()) {
            List<FortuneBagDetail> list = entry.getValue();
            FortuneBagDetail bagDetail = list.get(0);
            if (list.size() > 1) {
                Integer count = list.stream().map(FortuneBagDetail::getCount).reduce(0, (a, b) -> (a + b));
                bagDetail = new FortuneBagDetail();
                bagDetail.setBatchNo(list.get(0).getBatchNo());
                bagDetail.setSkuCode(list.get(0).getSkuCode());
                bagDetail.setSrcSkuCode(list.get(0).getSrcSkuCode());
                bagDetail.setCount(count);
            }
            result.add(bagDetail);
        }
        return result;

    }

    /**
     * 获取福袋明细 处理每一个福袋
     *
     * @param bagList  一个福袋明细集合
     * @param quantity 购买福袋数量
     * @return List<FortuneBagDetail>
     */
    private List<FortuneBagDetail> doEachBag(List<YgFortuneBag> bagList, int quantity) {
        List<FortuneBagDetail> bagDetailList = new ArrayList<>();
        //订单中福袋商品购买数量
        //福袋集合map
        Map<Integer, List<YgFortuneBag>> bagGroupMap = bagList.stream().collect(Collectors.groupingBy(YgFortuneBag::getGroup));
        for (Map.Entry<Integer, List<YgFortuneBag>> bagGroupEntry : bagGroupMap.entrySet()) {
            List<YgFortuneBag> bagGroupList = bagGroupEntry.getValue();
            List<FortuneBagDetail> list = doEachBagGroup(bagGroupList, quantity);
            bagDetailList.addAll(list);

        }

        // 校验抽选出的商品总数和福袋指定的商品总数是否一致
        int detailCount = bagDetailList.stream().map(FortuneBagDetail::getCount).reduce(0, (a, b) -> (a + b));
        int bagSkuCount = bagList.get(0).getBagSkuCount() * quantity;
        if (detailCount != bagSkuCount) {
            throw new RuntimeException("福袋抽选的商品数和指定的商品数不一致, skuCode =" + bagList.get(0).getSkuCode() + ", 指定数bagSkuCount =" + bagSkuCount
                    + ", 选定数detailCount=" + detailCount);
        }

        return bagDetailList;
    }

    /**
     * 获取福袋明细
     *
     * @param bagList  一个福袋阶梯的 福袋明细集合
     * @param quantity 福袋购买数量
     * @return List<FortuneBagDetail>
     */
    private List<FortuneBagDetail> doEachBagGroup(List<YgFortuneBag> bagList, int quantity) {
        bagList.sort(Comparator.comparing(YgFortuneBag::getPriority));
        List<FortuneBagDetail> bagDetailList = new ArrayList<>();
        for (int startPriority = 1; startPriority <= quantity; startPriority++) {
            int count = bagList.get(0).getCount();
            List<FortuneBagDetail> list = doEachBagPriority(bagList, count, startPriority);
            bagDetailList.addAll(list);
        }
        return bagDetailList;
    }

    /**
     * 获取福袋明细
     *
     * @param bagList       一个福袋阶梯的 福袋明细集合
     * @param count         福袋阶梯中商品数量
     * @param startPriority 起始优先级位置 （一个优先级表示一条福袋明细）
     * @return List<FortuneBagDetail>
     */
    private List<FortuneBagDetail> doEachBagPriority(List<YgFortuneBag> bagList, int count, int startPriority) {
        List<FortuneBagDetail> bagDetailList = new ArrayList<>();
        Integer group = bagList.get(0).getGroup();
        String skuCode = bagList.get(0).getSkuCode();
        for (int i = startPriority; i <= bagList.size(); i++) {
            YgFortuneBag fortuneBag = bagList.get(i - 1);
            //无库存 跳到下一个优先级
            if (fortuneBag.getStockCount() <= 0) {
                continue;
            }
            FortuneBagDetailResult result = doGetFortuneBagDetail(fortuneBag, count);
            bagDetailList.add(result.getFortuneBagDetail());
            count = result.getLastCount();
            if (count == 0) {
                return bagDetailList;
            }
        }
        if (count > 0) {
            int hasStock = bagList.stream().map(YgFortuneBag::getStockCount).reduce(0, (a, b) -> (a + b));
            if (hasStock >= count) {
                try {
                    List<FortuneBagDetail> list = doEachBagPriority(bagList, count, 1);
                    bagDetailList.addAll(list);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            } else {
                throw new RuntimeException("福袋商品库存不足,skuCode =" + skuCode + " ,group =" + group);
            }
        }
        return bagDetailList;
    }

    /**
     * 获取福袋明细
     *
     * @param fortuneBag 一个福袋明细
     * @param count      福袋阶梯中商品数量
     * @return FortuneBagDetailResult
     */
    private FortuneBagDetailResult doGetFortuneBagDetail(YgFortuneBag fortuneBag, int count) {
        int thisCount = 1;
//        int stockCount = fortuneBag.getStockCount();
        //库存足够直接返回
//        if (stockCount > count) {
//            thisCount = count;
//            count = 0;
//        } else {
//            count = count - stockCount;
//            thisCount = stockCount;
//        }
        --count;
        fortuneBag.setStockCount(fortuneBag.getStockCount() - 1);
        FortuneBagDetailResult result = new FortuneBagDetailResult();
        FortuneBagDetail bagDetail = new FortuneBagDetail();
        bagDetail.setBatchNo(fortuneBag.getBatchNo());
        bagDetail.setSkuCode(fortuneBag.getSkuCode());
        bagDetail.setSrcSkuCode(fortuneBag.getSrcSkuCode());
        bagDetail.setCount(thisCount);

        result.setLastCount(count);
        result.setFortuneBagDetail(bagDetail);
        return result;
    }


}
